#include <stdafx.h>
#include "utils.h"

void ConvertFftwToComplex(uint32_t width, uint32_t height, const float* ptrPacked, float* ptrComplexDest, uint32_t destStride)
{
	uint32_t destHeight = height;
	uint32_t destWidth = width / 2 + 1;

	uint32_t rem = width - destWidth;
	for (int y = 0; y < destHeight; ++y)
	{
		float* ptrDest = (float*)(((char*)ptrComplexDest) + y*destStride);
		const float* ptrSrc = (const float*)(((char*)ptrPacked) + y*(destWidth * 2 * sizeof(float)));
		if (y == 0)
		{
			memcpy(ptrDest, ptrSrc, destWidth*sizeof(float) * 2);
			for (int i = 0; i < rem; i++)
			{
				ptrDest[((width - 1) - i) * 2] = ptrSrc[(1 + i) * 2];
				ptrDest[((width - 1) - i) * 2 + 1] = -ptrSrc[(1 + i) * 2 + 1];
			}
		}
		else
		{
			memcpy(ptrDest, ptrSrc, destWidth*sizeof(float) * 2);
			for (int i = 0; i < rem; i++)
			{
				uint32_t x_ = destWidth + i;
				uint32_t y_ = (y);

				uint32_t x_r = width - x_;
				uint32_t y_r = height - y_;

				ptrDest[x_ * 2] = ((const float*)(((char*)ptrPacked) + y_r*(destWidth * 2 * sizeof(float))))[x_r * 2];
				ptrDest[x_ * 2 + 1] = -((const float*)(((char*)ptrPacked) + y_r*(destWidth * 2 * sizeof(float))))[x_r * 2 + 1];
			}
		}
	}
}

void ConvertComplexHermetianToFftw(uint32_t width, uint32_t height, const float* ptrComplex, float* ptrPacked, uint32_t srcStride, uint32_t destStride)
{
	uint32_t complexDestWidth = width / 2 + 1;
	for (uint32_t y = 0; y < height; ++y)
	{
		const float* ptrSrc = (const float*)(((char*)ptrComplex) + srcStride*y);
		float* ptrDst = (float*)(((char*)ptrPacked) + destStride*y);
		memcpy(ptrDst, ptrSrc, complexDestWidth*sizeof(float) * 2);
	}
}

bool IsNormalizationFactorDivBySize(double dbl)
{
	// if dbl is negative infinity, then we have "divide by size=width*height"
	if (std::isinf(dbl) && std::signbit(dbl) == true)
	{
		return true;
	}

	return false;
}

bool IsNormalizationFactorDivBySqrtSize(double dbl)
{
	// if dbl is positive infinity, then we have "divide by sqrt(size)=sqrt(width*height)"
	if (std::isinf(dbl) && std::signbit(dbl) == false)
	{
		return true;
	}

	return false;
}